# -*- encoding:utf-8 -*-
"""
@作者：jiajun_Tang
@文件名：gui_interface.py
@时间：2023/7/26  上午 10:31
@文档说明:
"""

import os
import cv2
import math
import yaml
import threading
import configparser
import numpy as np
from time import time, sleep
from copy import deepcopy
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QTimer
from PyQt5.QtGui import QPixmap, QImage, QPen, QColor, QBrush, QPainterPath
from PyQt5.QtWidgets import QMessageBox, QGraphicsScene, QGraphicsPixmapItem, QDialog, QLabel, \
    QStatusBar, QGraphicsEllipseItem, QGraphicsItem, QGraphicsLineItem, QGraphicsPolygonItem, QGraphicsPathItem

from data_acquisition.get_image import dis_consumer, get_detection_result, get_detection_result1, \
    get_detection_result2, get_detection_result3, get_detection_result4, get_detection_result5, \
    get_detection_result6, get_detection_result7
from QMyWidgets.QMyDialog import QMyDialog
from single_glass_front import Ui_MainWindow

# config = configparser.ConfigParser()
# config.read("../pd/deect.conf", encoding="utf-8")
with open('./config.yaml', encoding='utf-8') as f:
    defect_dict = yaml.load(f, Loader=yaml.SafeLoader)  # data dict


class query_window(QtWidgets.QMainWindow):
    def __init__(self, display_queue=None, height=None, all_width=None):
        QtWidgets.QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        # self.setFixedSize(self.width(), self.height())

        self.display_queue = display_queue
        self.height = height
        self.all_width = all_width

        # 添加状态栏
        self.statusbar = QStatusBar()
        self.labviewcorrd = QLabel('鼠标当前坐标点:')
        self.labviewcorrd.setMinimumWidth(150)
        self.statusbar.addWidget(self.labviewcorrd)
        self.labscenecorrd = QLabel('scene坐标：')
        self.labscenecorrd.setMinimumWidth(150)
        self.statusbar.addWidget(self.labscenecorrd)
        self.labitemcorrd = QLabel('item坐标：')
        self.labitemcorrd.setMinimumWidth(150)
        self.statusbar.addWidget(self.labitemcorrd)
        self.setStatusBar(self.statusbar)

        # 多选框事件
        # self.ui.checkBox_11.clicked.connect(self.query_formula)
        # self.ui.checkBox_21.clicked.connect

        # 使用graphicsView显示图片
        self.ui.graphicsView.setAlignment(QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft)
        self.ui.graphicsView.setStyleSheet("background-color: lightgray;")

        # 自适应图像显示
        self.ui.graphicsView.scene_img = QGraphicsScene()
        self.imgShow = QPixmap()
        # self.ui.graphicsView.scene_img.setBackgroundBrush(QtGui.QBrush(QtCore.Qt.red))
        self.ui.graphicsView.setScene(self.ui.graphicsView.scene_img)
        # 绘制一个点，防止QGraphicsScene绘图出错
        self.ui.graphicsView.scene_img.addRect(0, 0, 1, 1, QPen(QColor(Qt.lightGray)), QBrush(QColor(Qt.gray)))

        # QGraphicsView 视窗内的事件
        # self.ui.graphicsView.sigMouseMovePoint.connect(self.slotMouseMovePoint)
        self.ui.graphicsView.sigMouseMovePoint.connect(self.mouse_move_event)      # 鼠标移动后触发事件
        self.ui.graphicsView.sigMousePressPoint.connect(self.select_point_event)   # 点击视窗内容后的事件
        # self.ui.graphicsView.sigMouseReleasePoint.connect(self.slotMouseReleasePoint)

        # QTimer定时任务，定时更新主窗口显示内容
        # 创建一个QTimer对象
        self.data_refresh = QTimer(self)
        # QTimer定时任务，定时在显示检测
        self.data_refresh.start(1000)
        # 给QTimer设定一个时间，每到达这个时间一次就会调用一次该方法
        self.data_refresh.timeout.connect(self.draw_dot_plot)

        #
        self.points_list = []  # 检测数据列表
        self.glass_id = 0  # 检测的玻璃片ID
        self.a = 0  # 临时变量
        self.star_polygonItem = None  # 主窗口内的QGraphicsItem对象

        # 用于判断玻璃品级
        # dict1 = {[{var:0} for var in defect_dict]; 'Tom': 93, 'Jim': 80, 'Lily': 100}

    def draw_dot_plot(self):
        """ 获取点位，并根据不同的类型绘制不同的图像"""
        # self.ui.graphicsView.scene().clear()    # 删除QGraphicsScene上的所有对象
        # self.points_list = []
        # self.star_polygonItem = None

        # 获取检测的数据，传入的是队列形式
        # self.points_new = dis_consumer(self.display_queue)
        if self.display_queue and not self.display_queue.empty():
            self.points_new = dis_consumer(self.display_queue, rate=23)

        #     print('未发现数据队列对象！')
        #     if self.a == 0:
        #         sleep(1)
        #         self.points_new = get_detection_result()
        #         self.a = 1
        #     elif self.a == 1:
        #         self.points_new = get_detection_result1()
        #         self.a = 2
        #     elif self.a == 2:
        #         self.points_new = get_detection_result2()
        #         self.a = 3
            # elif self.a == 3:
            #     self.points_new = get_detection_result4()
            #     self.a = 4
            # elif self.a == 4:
            #     self.points_new = get_detection_result5()
            #     self.a = 5
            # elif self.a == 5:
            #     self.points_new = get_detection_result6()
            #     self.a = 6
            # elif self.a == 6:
            #     self.points_new = get_detection_result7()
            #     self.a = 7
        else:
            self.data_refresh.stop()
            return
                # self.points_new = get_detection_result()
                # self.a = 0

        # 判断是否是同一片玻璃上的
        glass_title = self.points_new[0]    # 返回结果的头信息
        glass_id = glass_title[0]           # 玻璃片ID
        glass_pname = glass_title[1]        # 工位编码

        if glass_id == self.glass_id:
            # 同一片玻璃,不做处理
            # pass
            print('同一片玻璃')
        else:
            # 不是同一片玻璃的情况下，将绘图清空
            self.ui.graphicsView.scene().clear()
            self.points_list = []
            self.glass_id = glass_id
            self.star_polygonItem = None
        # 删除元组列表第一个数据----即玻璃片ID数据
        del self.points_new[0]

        # 根据返回的检测信息绘制QGraphicsScene
        for point in self.points_new:
            window_x = point[0]
            window_y = point[1]
            defect_type = point[2]  # 缺陷类型，选择图形 , defect_img, accuracy,
            defect_length = point[5]  # 缺陷长度，选择颜色 ,
            defect_wide = point[6]  # 缺陷宽度

            # 根据缺陷长度选择颜色
            if 0.01 <= max(defect_length, defect_wide) < 0.05:
                color = QColor(Qt.blue)
            elif 0.5 <= max(defect_length, defect_wide) < 0.10:
                color = QColor(Qt.yellow)
            elif 0.10 <= max(defect_length, defect_wide) < 0.15:
                color = QColor(255, 0, 255)
            elif 0.15 <= max(defect_length, defect_wide) < 0.20:
                color = QColor(128, 0, 128)
            elif 0.20 <= max(defect_length, defect_wide) < 0.50:
                color = QColor(Qt.red)
            else:
                color = QColor(Qt.black)

            if 'coax' == glass_pname:
                # 绘制一个圆形
                self.ui.graphicsView.scene_img.addEllipse(window_x + 5, window_y + 5, 10, 10, QPen(color),
                                                          QBrush(color))
            elif 'back' == glass_pname:
                # 绘制一个矩形
                self.ui.graphicsView.scene_img.addRect(window_x, window_y + 5, 10, 10, QPen(color),
                                                       QBrush(color))
            elif 'tilt' == glass_pname:
                # 绘制一个三角形
                points = [(int(window_x), int(window_y - 5)),
                          (int(window_x - 4), int(window_y + 4)),
                          (int(window_x + 4), int(window_y + 4))]
                point_start = [QtCore.QPointF(*point) for point in points]
                polygon = QtGui.QPolygonF(point_start)
                self.ui.graphicsView.scene_img.addPolygon(polygon, QPen(color),
                                                          QBrush(color))

            self.points_list.append(point)

    def select_point_event(self, pt):
        """ 点击放大瑕疵细节图像"""
        print(self.ui.graphicsView.geometry())
        # print(self.ui.graphicsView.scene_img.geometry())

        # self.labviewcorrd.setText('view坐标:{},{}'.format(pt.x(), pt.y()))
        ptscene = self.ui.graphicsView.mapToScene(pt)  # 把view坐标转换为场景坐标

        self.x1 = ptscene.x()
        self.y1 = ptscene.y()
        # 根据鼠标点击的坐标点，判断触发事件
        # self.data_list = deepcopy(self.points_list)
        for point in self.points_list:
            # print(point[0], point[1])
            if abs(self.x1 - point[0] - 5) < 10 and abs(self.y1 - point[1] - 5) < 10:

                if self.star_polygonItem:
                    self.ui.graphicsView.scene_img.removeItem(self.star_polygonItem)
                    self.star_polygonItem = None

                self.insert_small_flags(pt)  # 插上小红旗

                window_x = point[0]
                window_y = point[1]
                defect_category = point[2]  # 缺陷类型
                defect_type = defect_dict.get(defect_category)   # 缺陷类别
                defect_img = point[3]  # 缺陷的细节图
                accuracy = point[4]  # 缺陷类型置信度
                defect_length = point[5]  # 缺陷长度
                defect_wide = point[6]  # 缺陷宽度

                self.dialog_fault = QMyDialog()
                self.dialog_fault.resize(480, 360)
                self.dialog_fault.setWindowTitle('瑕疵细节')
                self.verticalLayout = QtWidgets.QVBoxLayout(self.dialog_fault)
                self.verticalLayout.setObjectName("verticalLayout")

                # height, width, channel = defect_img.shape
                # qtimg = QtGui.QImage(defect_img.data, width, height, QImage.Format_RGB888)

                qpixmapimg = self.cvimg_to_qpixmapimg(defect_img)

                self.pic = QPixmap(qpixmapimg)
                self.label_pic = QLabel("show", self.dialog_fault)
                self.label_pic.setPixmap(self.pic)
                self.verticalLayout.addWidget(self.label_pic)

                # 瑕疵细节图及属性
                self.verticalLayout1 = QtWidgets.QVBoxLayout()
                self.verticalLayout1.setObjectName("verticalLayout1")
                self.label_20 = QtWidgets.QLabel()
                self.label_20.setObjectName("label_20")
                self.label_20.setText("缺陷种类及概率：{},  {:.2f} %".format(defect_type, accuracy))
                self.verticalLayout1.addWidget(self.label_20)
                self.label_21 = QtWidgets.QLabel()
                self.label_21.setObjectName("label_21")
                self.label_21.setText(f"缺   陷   宽： \t {defect_wide}")
                self.verticalLayout1.addWidget(self.label_21)
                self.label_22 = QtWidgets.QLabel()
                self.label_22.setObjectName("label_22")
                self.label_22.setText(f"缺   陷   长： \t {defect_length}")
                self.verticalLayout1.addWidget(self.label_22)
                self.label_23 = QtWidgets.QLabel()
                # self.label_23.setObjectName("label_23")
                # self.label_23.setText("缺 陷 面 积： \t XXX")
                # self.verticalLayout1.addWidget(self.label_23)

                self.horizontalLayout = QtWidgets.QHBoxLayout()
                self.horizontalLayout.setObjectName("horizontalLayout")
                self.label_24 = QtWidgets.QLabel()
                self.label_24.setObjectName("label_24")
                self.label_24.setText("检测是否正确：")
                self.horizontalLayout.addWidget(self.label_24)
                self.checkBox_21 = QtWidgets.QCheckBox()
                self.checkBox_21.setObjectName("checkBox_21")
                self.checkBox_21.setText("正确")
                self.horizontalLayout.addWidget(self.checkBox_21)
                self.checkBox_22 = QtWidgets.QCheckBox()
                self.checkBox_22.setObjectName("checkBox_21")
                self.checkBox_22.setText("错误")
                self.horizontalLayout.addWidget(self.checkBox_22)
                self.verticalLayout1.addLayout(self.horizontalLayout)

                self.verticalLayout.addLayout(self.verticalLayout1)

                self.dialog_fault.exec_()

    def insert_small_flags(self, pt):
        """ 鼠标点击窗口某一位置后，满足条件下，在鼠标点击位置插上小旗 """

        self.labviewcorrd.setText('view坐标:{},{}'.format(pt.x(), pt.y()))
        ptscene = self.ui.graphicsView.mapToScene(pt)  # 把view坐标转换为场景坐标

        self.x_real = ptscene.x()
        self.y_real = ptscene.y()

        self.labscenecorrd.setText('scene坐标:{:.0f},{:.0f}'.format(ptscene.x(), ptscene.y()))

        item = self.ui.graphicsView.scene_img.itemAt(ptscene, self.ui.graphicsView.transform())  # 在场景某点寻找图元--最上面的图元
        # 返回值：图元地址  参数1 场景点坐标； 参数2 ？？？？
        if item is not None:
            ptitem = item.mapFromScene(ptscene)  # 把场景坐标转换为图元坐标
            self.labitemcorrd.setText('item坐标:{:.0f},{:.0f}'.format(ptitem.x(), ptitem.y()))
            # 这里可以设旗子
            # 绘制一个红旗
            points = [(int(ptscene.x()), int(ptscene.y())),
                      (int(ptscene.x()), int(ptscene.y() - 20)),
                      (int(ptscene.x() + 10), int(ptscene.y() - 15)),
                      (int(ptscene.x()), int(ptscene.y() - 10))]
            # self.polygon = QtGui.QPolygonF([QtCore.QPointF(*point) for point in points])

            polygon = QtGui.QPolygonF([QtCore.QPointF(*point) for point in points])
            # self.ui.graphicsView.scene_img.addPolygon(self.polygon, QPen(QColor(Qt.red)),
            #                                           QBrush(QColor(Qt.red)))

            self.star_polygonItem = QGraphicsPolygonItem()
            self.star_polygonItem.setPolygon(polygon)
            self.star_polygonItem.setPen(QPen(Qt.red))
            self.star_polygonItem.setBrush(QBrush(Qt.red))
            # polygonItem.setPos(60, 260)
            self.ui.graphicsView.scene_img.addItem(self.star_polygonItem)

    def mouseMoveEvent(self, EV):
        print('鼠标移动了')

    def mouse_move_event(self, pt):
        """ 鼠标移动触发事件"""
        self.labviewcorrd.setText('view坐标:{},{}'.format(pt.x(), pt.y()))
        ptscene = self.ui.graphicsView.mapToScene(pt)  # 把view坐标转换为场景坐标

        self.x_real = ptscene.x()
        self.y_real = ptscene.y()
        print(self.x_real, self.y_real)

    def cvimg_to_qpixmapimg(self, cvimg):
        """ 将opencv读取的ndarray图像，转化为 QtGui.QPixmap

        Args:
            cvimg: ndarray
        Return:
        """

        if len(np.shape(cvimg)) == 2:
            cvimg = cv2.cvtColor(cvimg, cv2.COLOR_GRAY2RGB)
        # else:
        #     cvimg = cvimg[:, :, ::-1]

        height, width, channel = cvimg.shape
        qtimg = QtGui.QImage(cvimg.data, width, height, QImage.Format_RGB888)
        qpixmapimg = QPixmap.fromImage(qtimg)
        return qpixmapimg

if __name__ == "__main__":
    import sys

    QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)  # 添加对高分屏的支持
    app = QtWidgets.QApplication(sys.argv)
    window = query_window(display_queue=None, height=None, all_width=None)
    # window.showMaximized()  # 最大化窗口
    # window.setFixedSize(window.width(), window.height())
    window.show()
    sys.exit(app.exec_())
